package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/testdata/protoexample"
)

//获取请求参数
func main() {
	r := gin.Default()
	//-Get方法获取请求参数
	r.GET("/test1", func(c *gin.Context) {
		firstName := c.Query("first_Name")                           //获取不带默认值的请求参数
		lastName := c.DefaultQuery("last_Name", "last_default_name") //获取带默认值的请求参数
		c.String(http.StatusOK, "%s-%s", firstName, lastName)
	})

	// 	curl -X GET "http://localhost:8081/test1?first_Name=fmx&last_Name=lsx"
	// fmx-lsx
	// curl -X GET "http://localhost:8081/test1?first_Name=fmx"
	// fmx-last_default_name  //没有last_Name的请求参数就用默认的

	//-Body方法请求参数
	r.POST("/test2", func(c *gin.Context) {
		bodyByte, err := ioutil.ReadAll(c.Request.Body) //bodyByte是byte字节
		if err != nil {
			c.String(http.StatusBadRequest, err.Error())
			c.Abort()
		}
		c.String(http.StatusOK, string(bodyByte))
	})
	// 	curl -X POST "http://localhost:8081/test2" -d '{"name":"fmx"}'
	// '{name:fmx}'

	//-Bind参数的获取---struct
	r.GET("/test3", testing)
	r.POST("/test3", testing)
	// 	curl -X GET "http://localhost:8081/test3?name=fmx&address=guanzhou&birthday=2020-03-29"   绑定结构体的GET请求
	// person bind ok :{fmx guanzhou 2020-03-29 00:00:00 +0800 CST}

	// curl -X POST "http://localhost:8081/test3" -d "name=fmx&address=guanzhou&birthday=2020-03-29"  绑定结构体的POST请求
	// person bind ok :{fmx guanzhou 2020-03-29 00:00:00 +0800 CST}

	//-POST方法获取参数
	r.POST("/test4", func(c *gin.Context) {
		name := c.PostForm("name")
		address := c.DefaultPostForm("address", "undefind")
		c.String(http.StatusOK, "%s-%s", name, address)
	})
	// curl -X POST "http://localhost:8081/test4" -d "name=fmx&address=guanzhou"  //POST请求
	// fmx-guanzhou
	// curl -X POST "http://localhost:8081/test4" -d "name=fmx"
	// fmx-undefind

	//QueryMap和POSTFormMap的使用
	r.POST("/testuser", func(c *gin.Context) {
		name := c.PostForm("name")
		age := c.DefaultPostForm("age", "18")
		email := c.Query("email")
		tel := c.Request.URL.Query().Get("tel")
		sex := c.DefaultQuery("sex", "man")
		score := c.QueryMap("score")
		level := c.PostFormMap("level")

		c.JSON(http.StatusOK, gin.H{
			"name":  name,
			"age":   age,
			"email": email,
			"tel":   tel,
			"sex":   sex,
			"score": score,
			"level": level,
		})
	})
	// curl -X POST "http://localhost:8081/testuser" -d "tel=10086&email=fmx@qq.com&sex=女&score[a]=66&score[b]=88&name=lsx&age=22&level[a]=b&level[b]=a"

	//Param和
	r.GET("/user/:id", func(c *gin.Context) {
		// a GET request to /user/john
		id := c.Param("id") // id == "john"
		fmt.Println("===", id)
	})
	//curl -X GET "http://localhost:8081/user/john"

	//DataFromReader的使用
	r.GET("/avatar", func(c *gin.Context) {
		resp, err := http.Get("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2279235626,140379045&fm=26&gp=0.jpg")
		if err != nil && resp.StatusCode != http.StatusOK {
			c.Status(http.StatusServiceUnavailable)
			return
		}
		reader := resp.Body //获得响应体
		contentLength := resp.ContentLength
		contentType := resp.Header.Get("Content-Type")
		extraHeaders := map[string]string{
			"Content-Disposition": `attachment; filename="yangchaoyue.jpg"`,
		}
		c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
	})
	//访问"http://localhost:8081/avatar" 自动下载图片

	//表单提交复选框多选
	type myForm struct {
		Colors []string `form:"colors[]"`
	}
	r.GET("/checkbox", func(c *gin.Context) {
		var fakeForm myForm
		c.ShouldBind(&fakeForm)
		c.JSON(200, gin.H{"color": fakeForm.Colors})
	})

	//ProtoBuf 渲染（输出格式）
	r.GET("/someProtoBuf", func(c *gin.Context) {
		reps := []int64{int64(1), int64(2)}
		label := "test"
		// The specific definition of protobuf is written in the testdata/protoexample file.
		data := &protoexample.Test{
			Label: &label,
			Reps:  reps,
		}
		// Note that data becomes binary data in the response
		// Will output protoexample.Test protobuf serialized data
		c.ProtoBuf(http.StatusOK, data)
	})

	r.Run(":8081")
}

type Person struct {
	Name     string    `form:"name"`
	Address  string    `form:"address"`
	Birthday time.Time `form:"birthday" time_format:"2006-01-02"`
}

func testing(c *gin.Context) {
	var person Person
	if err := c.ShouldBind(&person); err == nil {
		//根据请求的content-type来做不同的binding操作
		c.String(http.StatusOK, "person bind ok :%v", person)
	} else {
		c.String(http.StatusOK, "person bind error :%v", err)
	}
}
